# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------

import logging
from piHAlibs import (evtputinq)
from .decoders import (addparser,adddecoder)
from .dfeatures import (add2md)
from .multievtq import MULTIEVTQ
from .servers import (SetupDaemons,SetupControllers)

logger = logging.getLogger()


def mevtq(pars):
    """
    param = ['INIT',name,evtout,function(largs)]
     name = Name to identify MEVTQ
     evtout = event output
       if parsed event : 'PARSER', function : ctrlparser
       if decoded event : 'DECODER', function : decoder
       if featured event : 'DFEATURE', function : dfeature
     evtinput = input for evtqueue
       if evtout : 'PARSER', evtinput : raw event
       if evtout : 'DECODER', evtinput : parsed event
       if evtout : 'DFEATURE', evtinput : decoded event
    param = ['STARTM',namedev]
     namedev = name + ':' + function
    param = ['[D,P,R]EVTINPUT',namedev,daemon]
     add already setup RX controllers 
     daemon = namedaemon:controller
    """
    if isinstance(pars,list):
        param = pars
    else:
        param = pars.split()
    if len(param) < 2: return False
    if param[0] == 'INIT':
        if len(param) < 4: return False
        p3 = param[3].split('(')
        namedev = param[1] + ':' + p3[0]
        largs = None
        if len(p3) == 2: largs = p3[1].rstrip(')')
        if namedev in SetupDaemons:
            logger.error('A daemon with this name % is already setup',namedev)
            return False
        else:
            #Init 
            try:
                dev = MULTIEVTQ()
            except Exception as e:
                logger.critical("%s : %s", repr(e.__class__), str(e))
                logger.error('Error in init daemon for %s',param[1])
                return False
            dev.name = param[1]
            dev.namedev = namedev
            SetupDaemons.setdefault(namedev)
            SetupDaemons[namedev] = dev
            if param[2] == 'PARSER':
                if largs:
                    res = addparser([namedev,largs],dev)
                else:
                    res = addparser([namedev],dev)
                dev.evtouts = dev.features
            elif param[2] == 'DECODER':
                res = adddecoder([namedev,param[3]],dev)
                dev.evtouts = dev.decoders
            elif param[2] == 'DFEATURE':
                res = add2md([namedev,param[3]],dev)
                dev.evtouts = dev.dfeatures
            if not res :
                logger.error('Error in adding %s %s to MULTIEVTQ',param[2],param[3])
                del  SetupDaemons[namedev]
                return False
            logger.debug("MULTIEVTQ correctly setup %s",repr(dev))
            return True
    else:
        namedev = param[1]
        if namedev not in SetupDaemons:
            logger.error('MULTIEVTQ %s is not yet setup',repr(namedev))
            return False
        ctrlparser = namedev.split(':')[1]
        dev = SetupDaemons[namedev]
    #Add an already setup RX controller
    if param[0] == 'REVTINPUT':
        if len(param) < 3: return False
        rawevtinput([param[1],param[2]])
        return True
    #Add an already setup RX parser
    if param[0] == 'PEVTINPUT':
        if len(param) < 3: return False
        parevtinput([param[1],param[2]])
        return True
    #Add an already setup RX decoder
    if param[0] == 'DEVTINPUT':
        if len(param) < 4: return False
        decevtinput([param[1],param[2],param[3]])
        return True
    #Start MULTICTRX
    if param[0] == 'STARTM':
        dev.tsetup()
        if dev.setup:
            dev.startm()
            logger.warning('Daemon of MULTIEVTQ correctly started : %s', repr(dev))
            return True
        else:
            logger.error('Error in setup Daemon of MULTIEVTQ %s', param)
            return False
    #Stop MULTICTRX
    if param[0] == 'STOPS':
        if dev.setup:
            dev.stops()
            logger.warning('Daemon of MULTIEVTQ correctly stopped')
            return True
        else:
            logger.error('Daemon of MULTIEVTQ is not yet setup and started %s',repr(dev))
            return False
    else:
        logger.error('Syntax error %s',repr(param))
        return False


def decevtinput(params):
    """
    params = [mevtq,rxctrl,decname]
    """
    if params[0] not in SetupDaemons: return False
    mevtq = SetupDaemons[params[0]]
    if params[1] not in SetupControllers: return False
    rxctrl = SetupDaemons[params[1]]
    if params[2] not in rxctrl.decodernames:
        logger.error("Decoder %s not in controller %s",params[2],params[1])
        return False
    decname = params[2]
    lnamedf = decname + '-FEATURES'
    i = rxctrl.dfeaturenames.index(lnamedf)
    ldfn,ldfr = rxctrl.dfeatures[i]
    if 'EVTPUTINQ' in ldfn:
        logger.error('EVTPUTINQ has been already added to MEVTQ')
        return False
    try:
        ldfr.append(evtputinq(mevtq.multievtq))
        ldfn.append('EVTPUTINQ')
        logger.info("Successfully added evtinput %s",params[1])
    except Exception as e:
        logger.error("%s : %s", repr(e.__class__), str(e))
        logger.error("In adding evtinput %s",params[1])
        return False
    return True


def parevtinput(params):
    """
    params = [mevtq,ctrlparser]
    """
    if params[0] not in SetupDaemons: return False
    mevtq = SetupDaemons[params[0]]
    if params[1] not in SetupControllers: return False
    name,ctrl = params[1].split(':')
    if ctrl[0] == 'N' : ctrl = ctrl[1:]
    rxctrl = SetupDaemons[params[1]]
    parser = ctrl + '-PARSER'
    if parser not in rxctrl.featurenames:
        logger.error("Parser %s not in controller %s",parser,params[1])
        return False
    try:
        rxctrl.decoders.append(evtputinq(mevtq.multievtq))
        rxctrl.decodernames.append('EVTPUTINQ')
        logger.info("Successfully added evtinput %s",params[1])
    except Exception as e:
        logger.error("%s : %s", repr(e.__class__), str(e))
        logger.error("In adding evtinput %s",params[1])
        return False
    return True


def rawevtinput(params):
    """
    params = [mevtq,rxctrl]
    """
    if params[0] not in SetupDaemons: return False
    mevtq = SetupDaemons[params[0]]
    if params[1] not in SetupControllers: return False
    rxctrl = SetupDaemons[params[1]]
    try:
        rxctrl.features.append(evtputinq(mevtq.multievtq))
        rxctrl.featurenames.append('EVTPUTINQ')
        logger.info("Successfully added evtinput %s",params[1])
    except Exception as e:
        logger.error("%s : %s", repr(e.__class__), str(e))
        logger.error("In adding evtinput %s",params[1])
        return False
    return True
